package utils;

import org.ejml.simple.SimpleMatrix;

public class TfIdf {
   
   public static SimpleMatrix doTfIdf(SimpleMatrix m) {
      /*
      m = m.transpose();
      
      double docCounts[] = new double[m.numCols()];
      
      
      //TF and get counts for idf
      for(int row = 0; row < m.numRows(); row++) {
      	
      	double rowMax = 0;
      	
      	for(int col = 0; col < m.numCols(); col++) {
      		if(m.get(row, col) > rowMax) {
      			rowMax = (int)m.get(row, col);
      		}
      		
      		//For IDF
      		if(m.get(row, col) > 0) {
      			docCounts[col]++;
      		}
      	}
      	
      	rowMax = Math.min(rowMax, MAX_TF_COUNT);
      	
      	for(int col = 0; col < m.numCols(); col++) {
      		m.set(row, col, m.get(row, col)/rowMax);
      		
      		//For IDF
      		docCounts[col] = Math.log(m.numRows() / (1+docCounts[col]));
      	}
      }
      
      
      
      
      //IDF
      for(int row = 0; row < m.numRows(); row++) {
      	
      	for(int col = 0; col < m.numCols(); col++) {
      		m.set(row, col, m.get(row, col)*docCounts[col]);
      	}
      	
      }
      
      m = m.transpose();
      
      return m;*/
      
      m = m.copy();
      //
      // Apply tfidf
      for (int i = 0; i < m.numRows(); i++) {
         int count = 0;
         for (int j = 0; j < m.numCols(); j++) {
            if (m.get(i, j) > 0) {
               count++;
            }
         }
         final double idf = Math.log((double) m.numCols() / count);
         for (int j = 0; j < m.numCols(); j++) {
            m.set(i, j, m.get(i, j) * idf);
         }
      }
      
      // Normalize
      for (int j = 0; j < m.numCols(); j++) {
         double sum = 0;
         for (int i = 0; i < m.numRows(); i++) {
            sum += square(m.get(i, j));
         }
         final double divisor = Math.sqrt(sum);
         for (int i = 0; i < m.numRows(); i++) {
            m.set(i, j, m.get(i, j) / divisor);
         }
      }
      
      return m;
   }
   
   private static double square(final double x)
   {
      return x * x;
   }
}
